home *** CD-ROM | disk | FTP | other *** search
/ AppleScript - The Beta Release / AppleScript - The Beta Release.iso / Development Tools / Sample Applications / MenuScripter 1.0d4.1 / MenuScripter Source / MSScript.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-11-24  |  35.6 KB  |  1,340 lines  |  [TEXT/MPS ]

  1. /*
  2.     MSScript.c
  3.     
  4.     Version 1.0d4
  5.     
  6.     Copyright © Apple Computer UK Ltd. 1992
  7.     
  8.     All rights reserved.
  9.     
  10.     Produced by : UK Developer Technical Support
  11.     AppleLink   : UK.DTS
  12.     
  13.     Contains OSA interface of MenuScripter.
  14.  
  15.     Change History :
  16.  
  17.       9-Jul-92 : NH : File created
  18.      12-Aug-92 : NH : Added checks for InitEditor
  19.      
  20.     Changes for 1.0d3:
  21.     
  22.         27-Aug-92 : NH : ExecuteScriptForMenu returns error code
  23.         
  24.     Changes for 1.0d4:
  25.         
  26.         14-Nov-92 : NH : Gustav now system Extension so don't try to launch it!
  27.                                          Remove editing from menu item
  28. */
  29.  
  30. #include <Memory.h>
  31. #include <Resources.h>
  32. #include <TextEdit.h>
  33. #include <Controls.h>
  34. #include <Dialogs.h>
  35. #include <Errors.h>
  36. #include <Files.h>
  37. #include <Folders.h>
  38. #include <Components.h>
  39. #include <AppleEvents.h>
  40. #include <OSA.h>
  41. #include <AppleScript.h>
  42. #include <AERegistry.h>
  43. #include <Processes.h>
  44.  
  45. #include "MSGlobals.h"
  46. #include "MSUtils.h"
  47. #include "MSAEUtils.h"
  48. #include "MSWindow.h"
  49.  
  50. /*
  51.     Each menu (or menu item) can have a script associated with it. This
  52.     script has an ID equal to 32 * theMenuID + theItem number. A script
  53.     with an item number of 0 applies to the whole menu unless it is 
  54.     overridden by a particular script for an item in the menu.
  55.     
  56.     Scripts are stored in two resource types
  57.         'scpt' is a compiled script as returned by OSAStore()
  58.         'SCPT' is a raw text script as defined in the resource file
  59.         
  60.     At open application time scripts are built from the 'SCPT' resources 
  61.     if there are not any existing complied scripts of that resource ID.
  62.     These are stored in the preferences file for the application.
  63.     
  64.     One problem with the scripted menu commands is that if the application
  65.     name is changed the target is no longer found. This may be addressed later.
  66.  
  67.     In order to execute the scripts the application needs to connect to the
  68.     AppleScript component (called Gustav in the Alpha release). The search
  69.     of the available volumes uses the desktop database. Hence the search is
  70.     limited to hard disks.
  71.     
  72. */
  73.  
  74. #define kMaxScriptsInApp 100
  75. #define kCompiledScriptType kOSAScriptResourceType
  76. #define kTextScriptType 'SCPT'
  77.  
  78. struct MyScriptRecord {
  79.   OSAID  theScriptID;
  80.     short  theResID;
  81. };
  82.  
  83. typedef struct MyScriptRecord MyScriptRecord;
  84.  
  85. ComponentInstance gScriptingComponent;
  86. short             gActiveMenuItem;
  87. AESendProcPtr     oldSendProc;
  88. long              refCon;
  89. MyScriptRecord   *menuScripts;
  90. short             gNumScripts;
  91. short             gPrefsRefFile;
  92.  
  93. /*
  94.     These are used in documentation but not defined in the interfaces
  95. */
  96.  
  97. #ifndef kComponentNotFound
  98. #define kComponentNotFound -1
  99. #endif
  100.  
  101. #define kAEDontRecord 0x00001000
  102.  
  103. pascal OSErr MySendProc(const AppleEvent*        theAppleEvent,
  104.                                                 AppleEvent*                    reply,
  105.                                                 AESendMode                     sendMode,
  106.                                                 AESendPriority             sendPriority,
  107.                                                 long                           timeOutInTicks,
  108.                                                 IdleProcPtr                  idleProc,
  109.                                                 EventFilterProcPtr  filterProc,
  110.                                                 long                           refCon)
  111.     { 
  112. #pragma unused (refCon)
  113.  
  114.         DescType     typeCode;
  115.         Size         descSize;
  116.         OSErr        myErr;
  117.         OSErr        ignoreErr;
  118.         OSType       whatEvent;
  119.         AppleEvent   myCopyAEvt;
  120.         
  121.         myErr = AEDuplicateDesc(theAppleEvent, &myCopyAEvt);
  122.     
  123.         myErr = AEGetAttributePtr(&myCopyAEvt,
  124.                                                             keyEventIDAttr,
  125.                                                             typeType,
  126.                                                             &typeCode,
  127.                                                             (Ptr) &whatEvent,
  128.                                                             sizeof(whatEvent),
  129.                                                             &descSize);
  130.                                                             
  131.         ignoreErr = AEDisposeDesc(&myCopyAEvt);
  132.         
  133.         if (myErr != noErr)
  134.           {
  135.                 whatEvent = '????';
  136.             }
  137.         
  138.         /*
  139.             Record the final Set Data that occurs due to a script
  140.             'gdte' = id sent to get 'aete' resource from app, dealt with
  141.             by system handler.
  142.         */
  143.       if ((sendMode & kAEDontRecord) && 
  144.                 ((whatEvent!=kAEGetData) && (whatEvent!='gdte')))
  145.           sendMode = sendMode - kAEDontRecord;
  146.             
  147.         /* will be this when a5 bug fixed
  148.         return((*oldSendProc)(theAppleEvent,
  149.                                      reply,
  150.                                      sendMode,
  151.                                      sendPriority,
  152.                                      timeOutInTicks,
  153.                                      idleProc,
  154.                                      filterProc,
  155.                                      refCon));
  156.         */
  157.         
  158.         return(AESend(theAppleEvent,
  159.                       reply,
  160.                                     sendMode,
  161.                                     sendPriority,
  162.                                     timeOutInTicks,
  163.                                     idleProc,
  164.                                     filterProc));                            
  165.     }    /* MySendProc */
  166.     
  167. pascal OSAID GetScriptIDForResID(short lookForID)
  168.     {
  169.         short ctr;
  170.         
  171.         for (ctr=0; ctr<gNumScripts; ctr++)
  172.             {
  173.                 if (menuScripts[ctr].theResID==lookForID)
  174.                     return(menuScripts[ctr].theScriptID);
  175.             }
  176.             
  177.         return(kOSANullScript);
  178.     }
  179.     
  180. /*
  181.     Name : GetOpenPreferencesResourceFile
  182.     Purpose : Opens the prefs file, in the system prefs folder
  183.               creating it if it is not found. Sets the current
  184.                         resource file to the prefs file so that resources
  185.                         will be read from there in preference to the app
  186.                         if they have been overridden, and new resources
  187.                         will be created in it.
  188. */
  189.     
  190. pascal OSErr GetOpenPreferencesResourceFile(short *theRefNum)
  191.     {
  192.       short  foundVRefNum;
  193.         long   foundDirID;
  194.         OSErr  myErr;
  195.         
  196.         myErr = FindFolder(kOnSystemDisk,
  197.                            kPreferencesFolderType,
  198.                                              kCreateFolder,
  199.                          &foundVRefNum,
  200.                                              &foundDirID);
  201.                                              
  202.         if (myErr==noErr)
  203.             {
  204.  
  205.                 *theRefNum = HOpenResFile(foundVRefNum, foundDirID, "\pMenuScripter Prefs", fsWrPerm);
  206.                 myErr = ResError();
  207.                 
  208.                 if (myErr==fnfErr)
  209.                     {
  210.                         HCreateResFile(foundVRefNum, foundDirID, "\pMenuScripter Prefs");
  211.                         myErr = ResError();
  212.  
  213.                         *theRefNum = HOpenResFile(foundVRefNum, foundDirID, "\pMenuScripter Prefs", fsWrPerm);
  214.                         myErr = ResError();
  215.                     }
  216.             }
  217.         return(myErr);
  218.     }
  219.     
  220. pascal OSErr ClosePrefsResFile(short theRefNum)
  221.     {
  222.         CloseResFile(theRefNum);
  223.         return(ResError());
  224.     }
  225.  
  226. /*
  227.     Name : AddMenuScript
  228.     Purpose : Adds a compiled script OSAID into the
  229.               global menuScripts array for later access
  230. */
  231. pascal void AddMenuScript(short thisID, OSAID thisScriptID)
  232.     {
  233.         if (gNumScripts<kMaxScriptsInApp)
  234.             {
  235.                 menuScripts[gNumScripts].theResID    = thisID;
  236.                 menuScripts[gNumScripts].theScriptID = thisScriptID;
  237.                 gNumScripts ++;
  238.             }
  239.     }
  240.  
  241. /*
  242.     Name : BuildMenuScripts
  243.     Purpose : Reads compiled scripts from the prefs file,
  244.               Any uncompiled scripts ('SCPT' resources with
  245.                         no 'Scpt' of same id are compiled, and a compiled
  246.                         version stored in the prefs file. Any which fail
  247.                         to compile are ignored.
  248. */
  249. pascal void BuildMenuScripts(void)
  250.     {
  251.         short   numScripts;
  252.         short   index;
  253.         short   thisID;
  254.         ResType thisType;
  255.         Handle  myScript;
  256.         AEDesc  myLoadScriptDesc;
  257.         AEDesc  myStoreScriptDesc;
  258.         OSAID   myLoadID;
  259.         OSErr   myErr;
  260.         OSErr   ignoreErr;
  261.         Str255  resName;
  262.         
  263.         GetOpenPreferencesResourceFile(&gPrefsRefFile);
  264.         
  265.         gNumScripts = 0;
  266.         
  267.         menuScripts = (MyScriptRecord *)NewPtr(sizeof(MyScriptRecord)*kMaxScriptsInApp);
  268.         
  269.         numScripts  = Count1Resources(kCompiledScriptType);
  270.         for (index=0; index <numScripts; index++)
  271.             {
  272.                 myScript  = Get1IndResource(kCompiledScriptType, index+1);
  273.                 GetResInfo(myScript, &thisID, &thisType, resName);
  274.                 
  275.               HLock(myScript);
  276.                 
  277.                 myErr = AECreateDesc(typeOSAGenericStorage,
  278.                                                          (Ptr)*myScript,
  279.                                                          GetHandleSize(myScript),
  280.                                                          &myLoadScriptDesc);
  281.                 
  282.                 HUnlock(myScript);
  283.                 
  284.                 if (myErr==noErr)
  285.                     {
  286.                         myLoadID = 0; // Added for Gustav a8
  287.                         
  288.                         myErr = OSALoad(gScriptingComponent,
  289.                                                         &myLoadScriptDesc,
  290.                                                         0,
  291.                                                         &myLoadID);
  292.                                                         
  293.                       if (myErr==noErr)
  294.                             AddMenuScript(thisID,myLoadID);
  295.                     }
  296.                 
  297.                 ignoreErr = AEDisposeDesc(&myLoadScriptDesc);
  298.             }
  299.             
  300.         numScripts  = CountResources(kTextScriptType);
  301.         for (index=0; index <numScripts; index++)
  302.             {
  303.                 myScript  = GetIndResource(kTextScriptType, index+1);
  304.                 GetResInfo(myScript, &thisID, &thisType, resName);
  305.                 
  306.                 if (GetScriptIDForResID(thisID)==kOSANullScript)
  307.                     {
  308.                         HLock(myScript);
  309.                         
  310.                         myErr = AECreateDesc(typeChar,
  311.                                                                  (Ptr)*myScript,
  312.                                                                  GetHandleSize(myScript),
  313.                                                                  &myLoadScriptDesc);
  314.                         
  315.                         HUnlock(myScript);
  316.                         
  317.                         if (myErr==noErr)
  318.                             {
  319.                                 myLoadID = 0; // Added for alpha 8
  320.                                 
  321.                                 myErr = OSACompile(gScriptingComponent,
  322.                                                                      &myLoadScriptDesc,
  323.                                                                      0,
  324.                                                                      &myLoadID);
  325.                                                                 
  326.                                 if (myErr==noErr)
  327.                                     AddMenuScript(thisID,myLoadID);
  328.                                     
  329.                                 if (myErr==noErr)
  330.                                     {
  331.                                         myErr = OSAStore(gScriptingComponent,
  332.                                                                          myLoadID,
  333.                                                                          typeOSAGenericStorage,
  334.                                                                          0,
  335.                                                                          &myStoreScriptDesc);
  336.                                                                          
  337.                                         if (myErr==noErr)
  338.                                             {
  339.                                                 myScript = myStoreScriptDesc.dataHandle;
  340.                                                 
  341.                                                 HandToHand(&myScript);                                 
  342.                                                 AddResource(myScript, kCompiledScriptType, thisID, "\pMenu Script");
  343.                                             }
  344.                                         
  345.                                         myErr = AEDisposeDesc(&myStoreScriptDesc);
  346.                                     }
  347.                                     
  348.                             }
  349.                         
  350.                         ignoreErr = AEDisposeDesc(&myLoadScriptDesc);
  351.                     }
  352.             }
  353.     }
  354.     
  355. /*
  356.     Name:   InitEditorScripting
  357.     Purpose:Connects to the AppleScript component.
  358.             If not currently running it searches all volumes
  359.                     with a desktop database, and launches it if found.
  360.                     It then tries for approx. 1 min to connect to the
  361.                     newly launched AppleScript component.
  362. */
  363. pascal OSErr InitEditorScripting(void)
  364.     {
  365.       OSErr                myErr;
  366.         ComponentDescription descr;
  367.         ComponentDescription capabilities;
  368.         Component            myComponent;
  369.         EventRecord          myEvent;
  370.         short                retryCount;
  371.         
  372.         SetCursor(&waitCursor);
  373.         
  374.         // Out of date stuff - now it's an extension!
  375.         // myErr = EnsureGustavIsLaunched();
  376.         // if (myErr)
  377.         //     return(myErr);
  378.             
  379.         retryCount = 0;
  380.         
  381.         do {
  382.           
  383.             /* Don't lose the high level events - expect a null back */
  384.             
  385.           myErr = WaitNextEvent(mDownMask+mUpMask+keyDownMask+keyUpMask+autoKeyMask,
  386.                                   &myEvent,
  387.                                                         240, /* 4 seconds */
  388.                                                         nil);
  389.         
  390.             descr.componentType         = kOSAComponentType;
  391.             descr.componentSubType      = kAppleScriptSubtype;
  392.             descr.componentManufacturer = (OSType) 0;
  393.             descr.componentFlags        = kOSASupportsCompiling + 
  394.                                           kOSASupportsGetSource + 
  395.                                                                         kOSASupportsAESending;
  396.                                                                         
  397.             descr.componentFlagsMask    = descr.componentFlags;
  398.             
  399.             myComponent = FindNextComponent(nil, &descr);
  400.             
  401.             retryCount++;
  402.             
  403.         } while (myComponent==nil && retryCount<15); /* Try for one minute */
  404.         
  405.         if (myComponent==nil)
  406.           return(kComponentNotFound);
  407.         else
  408.           {
  409.                 myErr = GetComponentInfo(myComponent,
  410.                                                                  &capabilities,
  411.                                                                  nil,
  412.                                                                  nil,
  413.                                                                  nil);
  414.                                                                  
  415.               gScriptingComponent = OpenComponent(myComponent);
  416.                                                                                                     
  417.                 if (gScriptingComponent==nil)
  418.                     return(kComponentNotFound);
  419.             }
  420.             
  421.         myErr = OSAGetSendProc(gScriptingComponent,
  422.                                                      &oldSendProc,
  423.                                                      &refCon);
  424.                                                 
  425.         myErr = OSASetSendProc(gScriptingComponent,
  426.                                                      MySendProc,
  427.                                                      0);
  428.         
  429.         menuScripts = nil;
  430.         
  431.         BuildMenuScripts();
  432.                 
  433.         SetCursor(&qd.arrow);
  434.                     
  435.         return(myErr);
  436.     }
  437.     
  438. /*
  439.     Name    : CloseEditorScripting
  440.     Purpose : Shutdown of editor scripting capabilities
  441. */
  442. pascal OSErr CloseEditorScripting(void)
  443.     {
  444.       OSErr myErr;
  445.         short ctr;
  446.         
  447.         ClosePrefsResFile(gPrefsRefFile);
  448.         
  449.         for (ctr=0; ctr<gNumScripts; ctr++)
  450.             myErr = OSADispose(gScriptingComponent, menuScripts[ctr].theScriptID);
  451.         
  452.         myErr = CloseComponent(gScriptingComponent);
  453.         
  454.         return(myErr);
  455.     }
  456.     
  457. /*
  458.     Name:    DisplayErrorInScript
  459.     Purpose: Put up an alert showing the error text for the last error.
  460.              Also selects the responsible text in theHTE if one is supplied
  461. */
  462.  
  463. pascal void DisplayErrorInScript(TEHandle theHTE)
  464.     {
  465.         Str255   errorMessageText;
  466.         AEDesc   errRangeDesc;
  467.         AEDesc   errRecordDesc;
  468.         AEDesc   errTextDesc;
  469.         AEDesc   errNumberDesc;
  470.         DescType typeCode;
  471.         Size     actSize;
  472.         OSErr    myErr;
  473.         OSErr    ignoreErr;
  474.         OSErr    errorNumber;
  475.         short    errorStart;
  476.         short    errorEnd;
  477.         
  478.         SetCursor(&qd.arrow);
  479.         
  480.         myErr = OSAScriptError(gScriptingComponent,
  481.                                                      kOSAErrorNumber,
  482.                                                      typeShortInteger,
  483.                                                      &errNumberDesc);
  484.         
  485.         myErr = GetIntegerFromDescriptor(&errNumberDesc, &errorNumber);
  486.                 
  487.         ignoreErr = AEDisposeDesc(&errNumberDesc);
  488.         
  489.         myErr = OSAScriptError(gScriptingComponent,
  490.                                                      kOSAErrorMessage,
  491.                                                      typeChar,
  492.                                                      &errTextDesc);
  493.                                                      
  494.         myErr = GetPStringFromDescriptor(&errTextDesc, errorMessageText);
  495.         
  496.         ignoreErr = AEDisposeDesc(&errTextDesc);
  497.         
  498.         if (theHTE)
  499.             {
  500.                 myErr = OSAScriptError(gScriptingComponent,
  501.                                                              kOSAErrorRange,
  502.                                                              typeOSAErrorRange,
  503.                                                              &errRangeDesc);
  504.                                                              
  505.                 myErr = AECoerceDesc(&errRangeDesc, typeAERecord, &errRecordDesc);
  506.                 
  507.                 ignoreErr = AEDisposeDesc(&errRangeDesc);
  508.                 
  509.                 myErr = AEGetKeyPtr(&errRecordDesc,
  510.                                     keyOSASourceStart,
  511.                                                         typeShortInteger,
  512.                                                         &typeCode,
  513.                                                         (Ptr)&errorStart,
  514.                                                         sizeof(errorStart),
  515.                                                         &actSize);
  516.                                                         
  517.                 myErr = AEGetKeyPtr(&errRecordDesc,
  518.                                     keyOSASourceEnd,
  519.                                                         typeShortInteger,
  520.                                                         &typeCode,
  521.                                                         (Ptr)&errorEnd,
  522.                                                         sizeof(errorEnd),
  523.                                                         &actSize);
  524.                                                         
  525.                 ignoreErr = AEDisposeDesc(&errRecordDesc);
  526.                 
  527.                 TESetSelect(errorStart, errorEnd, theHTE);
  528.             }
  529.         
  530.         ShowError(errorMessageText, errorNumber);
  531.     }
  532. /*
  533.     Name    : CompileDocument
  534.     Purpose : Compiles the text of the supplied document - does NOT keep
  535.               a compiled version - merely checks that it will compile for now
  536. */
  537. pascal OSErr CompileDocument(DPtr theDoc)
  538.     {
  539.         OSErr             myErr;
  540.         OSErr             ignoreErr;
  541.         TEHandle          theHTE;
  542.         AEDesc            windowTextDesc;
  543.         AEDesc            myCompiledText;
  544.         AEDesc            styledTextDesc;
  545.         AEDesc            textStyleDesc;
  546.         AEDesc            rawTextDesc;
  547.         OSAID             myScriptID;
  548.         
  549.         /*
  550.           Initialise handles
  551.         */
  552.         
  553.         myCompiledText.dataHandle = nil;
  554.         windowTextDesc.dataHandle = nil;
  555.         
  556.         theHTE = theDoc->theText;
  557.         
  558.         HLock((Handle)(**theHTE).hText);
  559.         myErr = AECreateDesc(typeChar,
  560.                                                  (Ptr)&(*(**theHTE).hText)[0],
  561.                                                  (**theHTE).teLength,
  562.                                                  &windowTextDesc);
  563.                                                  
  564.         HUnlock((Handle)(**theHTE).hText);
  565.         
  566.         if (myErr==noErr)
  567.             {
  568.                 myScriptID = 0; // Added for Gustav 1.0a8
  569.                 
  570.                 myErr = OSACompile(gScriptingComponent,
  571.                                    &windowTextDesc,
  572.                                                      0,
  573.                                                      &myScriptID);
  574.                 
  575.                 if (myErr==noErr)
  576.                   {
  577.                         myErr = OSAGetSource(gScriptingComponent,
  578.                                                                  myScriptID,
  579.                                                                  typeStyledText,
  580.                                                                  &myCompiledText);
  581.                         if (myErr==noErr)
  582.                             {
  583.                                 styledTextDesc.dataHandle = nil;
  584.                                 textStyleDesc.dataHandle  = nil;
  585.                                 rawTextDesc.dataHandle    = nil;
  586.                             
  587.                               /*
  588.                                     Coerce to an AERecord and then extract the parts of the
  589.                                     styled text
  590.                                 */
  591.                                 myErr = AECoerceDesc(&myCompiledText, typeAERecord, &styledTextDesc);
  592.                                 
  593.                                 myErr = AEGetKeyDesc(&styledTextDesc,
  594.                                                      keyAEText,
  595.                                                                          typeChar,
  596.                                                                          &rawTextDesc);
  597.                                                                          
  598.                                 myErr = AEGetKeyDesc(&styledTextDesc,
  599.                                                      keyAEStyles,
  600.                                                                          typeScrapStyles,
  601.                                                                          &textStyleDesc);
  602.                                                                          
  603.                                 TESetSelect(0,32000, theHTE);
  604.                                 TEDelete(theHTE);
  605.                                 
  606.                                 HLock((Handle)rawTextDesc.dataHandle);
  607.                                                                          
  608.                                 TEStylInsert((const void *) (*rawTextDesc.dataHandle),
  609.                                              GetHandleSize(rawTextDesc.dataHandle),
  610.                                                          (StScrpHandle) textStyleDesc.dataHandle,
  611.                                                          theHTE);
  612.                                                          
  613.                                 HUnlock((Handle)rawTextDesc.dataHandle);
  614.                                 
  615.                                 if (textStyleDesc.dataHandle)
  616.                                     ignoreErr = AEDisposeDesc(&textStyleDesc);
  617.                         
  618.                                 if (rawTextDesc.dataHandle)
  619.                                     ignoreErr = AEDisposeDesc(&rawTextDesc);
  620.  
  621.                                 if (styledTextDesc.dataHandle)
  622.                                     ignoreErr = AEDisposeDesc(&styledTextDesc);
  623.  
  624.                             }
  625.                         
  626.                     }
  627.                 else
  628.                     DisplayErrorInScript(theHTE);
  629.                     
  630.                 if (myErr==noErr)
  631.                   ignoreErr = OSADispose(gScriptingComponent,
  632.                                            myScriptID);
  633.             }
  634.             
  635.         if (myCompiledText.dataHandle)
  636.             ignoreErr = AEDisposeDesc(&myCompiledText);
  637.             
  638.         if (windowTextDesc.dataHandle)
  639.             ignoreErr = AEDisposeDesc(&windowTextDesc);
  640.  
  641.         return(myErr);
  642.         
  643.     }
  644.     
  645. /*
  646.     Name    : ExecuteDocument
  647.     Purpose : Compiles the text of the supplied document and then executes it
  648.               - does NOT keep a compiled version after execution
  649. */
  650. pascal OSErr ExecuteDocument(DPtr theDoc)
  651.   {
  652.         OSErr             myErr;
  653.         OSErr             ignoreErr;
  654.         TEHandle          theHTE;
  655.         AEDesc            windowTextDesc;
  656.         AEDesc            myCompiledText;
  657.         OSAID             myScriptID;
  658.         OSAID             myExecutedScriptID;
  659.         
  660.         /*
  661.           Initialise handles
  662.         */
  663.         
  664.         myCompiledText.dataHandle = nil;
  665.         windowTextDesc.dataHandle = nil;
  666.         
  667.         theHTE = theDoc->theText;
  668.         
  669.         HLock((Handle)(**theHTE).hText);
  670.         myErr = AECreateDesc(typeChar,
  671.                                                  (Ptr)&(*(**theHTE).hText)[0],
  672.                                                  (**theHTE).teLength,
  673.                                                  &windowTextDesc);
  674.                                                  
  675.         HUnlock((Handle)(**theHTE).hText);
  676.         
  677.         if (myErr==noErr)
  678.             {
  679.                 myScriptID = 0; // Added for Gustav 1.0a8
  680.                 
  681.                 myErr = OSACompile(gScriptingComponent,
  682.                                    &windowTextDesc,
  683.                                                      0,
  684.                                                      &myScriptID);
  685.                                                      
  686.                 if (myErr==noErr)
  687.                   {
  688.                         myErr = OSAExecute(gScriptingComponent,
  689.                                            myScriptID,
  690.                                                              kOSANullScript,
  691.                                                              0,
  692.                                                              &myExecutedScriptID);
  693.                 
  694.                       if (myErr!=noErr)
  695.                           DisplayErrorInScript(theHTE);
  696.                             
  697.                         myErr = OSAGetSource(gScriptingComponent,
  698.                                                                  myScriptID,
  699.                                                                  typeStyledText,
  700.                                                                  &myCompiledText);
  701.                         if (myErr==noErr)
  702.                             {
  703.                                 /* Zap current contents and
  704.                                      replace with returned source */
  705.                                                                  
  706.                                 TESetSelect(0, 32000, theHTE);
  707.                                 TEDelete(theHTE);
  708.  
  709.                                 myErr = GetStyledTextFromDescIntoTEHandle(&myCompiledText, theHTE);
  710.                                     
  711.                                 if (myErr==noErr)
  712.                                     ignoreErr = OSADispose(gScriptingComponent,
  713.                                                                                  myExecutedScriptID);
  714.                             }
  715.                         
  716.                     }
  717.                 else
  718.                     DisplayErrorInScript(theHTE);
  719.                     
  720.                 if (myErr==noErr)
  721.                   ignoreErr = OSADispose(gScriptingComponent,
  722.                                            myScriptID);
  723.             }
  724.             
  725.         if (myCompiledText.dataHandle)
  726.             ignoreErr = AEDisposeDesc(&myCompiledText);
  727.             
  728.         if (windowTextDesc.dataHandle)
  729.             ignoreErr = AEDisposeDesc(&windowTextDesc);
  730.  
  731.         return(myErr);        
  732.     }
  733.  
  734. /* 
  735.     Name   : ScriptForMenuExists
  736.     Purpose: Tests for the existance of a valid script for a given menu item             
  737. */
  738.     
  739. pascal OSErr ScriptForMenuExists(short theMenu, short theItem, Boolean *exists)
  740.     {
  741.         short  resID;
  742.         OSAID  myScriptID;
  743.         OSErr  myErr;
  744.         
  745.         myErr = noErr;
  746.         
  747.         resID = (theMenu<<5) + theItem;
  748.         
  749.         myScriptID = GetScriptIDForResID(resID);
  750.         
  751.         if (myScriptID==kOSANullScript)
  752.             if (theItem!=0)
  753.                 myErr = ScriptForMenuExists(theMenu, 0, exists);
  754.             else
  755.                 *exists = false;
  756.         else
  757.           *exists = true;
  758.                 
  759.         return(myErr);        
  760.     } /* ScriptForMenuExists */
  761.     
  762.     
  763. /* 
  764.     Name   : ExecuteScriptForMenu
  765.     Purpose: Executes a script associated with the menu item.
  766.              Should be called only after ScriptForMenuExists
  767.                      returns exists.
  768. */    
  769. pascal OSErr ExecuteScriptForMenu(short theMenu, short theItem)
  770.   {
  771.         short  resID;
  772.         OSAID  myScriptID;
  773.         OSAID  myExecuteID;
  774.         OSErr  myErr;
  775.         OSErr  ignoreErr;
  776.                 
  777.         resID = (theMenu<<5) + theItem;
  778.         
  779.         myScriptID = GetScriptIDForResID(resID);
  780.                 
  781.         if (myScriptID==kOSANullScript)
  782.           {
  783.                 resID = (theMenu<<5); /* look for a script for the whole menu - item 0 */
  784.                 myScriptID = GetScriptIDForResID(resID);
  785.             }
  786.         
  787.         if (myScriptID != kOSANullScript)
  788.           {
  789.                 gActiveMenuItem = theItem;
  790.                 
  791.                 myErr = OSAExecute(gScriptingComponent,
  792.                                                      myScriptID,
  793.                                                      kOSANullScript,
  794.                                                      0,
  795.                                                      &myExecuteID);
  796.                                                      
  797.                 ignoreErr = OSADispose(gScriptingComponent,
  798.                                        myExecuteID);
  799.                 
  800.                 gActiveMenuItem = 0;
  801.             }
  802.  
  803.         return(myErr);
  804.     }
  805.  
  806. /*
  807.     Name :   GetScriptActiveItem
  808.     Purpose : Used by SVAppleEvents for the active item property of a menu.
  809.               Allows a script associated with more than one menu item to
  810.                         find which menu item it was called by.
  811. */
  812. pascal short GetScriptActiveItem(void)
  813.     {
  814.         return(gActiveMenuItem);
  815.     }
  816.     
  817. /*
  818.     Routines used in the StyledTextEdit Dialog Item
  819. */
  820.  
  821. struct StyleTextInfo {
  822.     ControlHandle theScrollBar;
  823.     TEHandle      theTEHandle;
  824. };
  825.  
  826. typedef struct StyleTextInfo StyleTextInfo;
  827.  
  828. typedef StyleTextInfo *pStyleTextInfo;
  829.  
  830. pascal void DrawStyledTextEditRec(DialogPtr theDialog, short theItem)
  831.     {
  832.         short   theType;
  833.         Handle  theHandle;
  834.         Rect    itemRect;
  835.                 
  836.         GetDItem(theDialog, theItem, &theType, &theHandle, &itemRect);
  837.         FrameRect(&itemRect);
  838.         InsetRect(&itemRect, 5, 5);
  839.         
  840.         TEUpdate(&itemRect, ((pStyleTextInfo) GetWRefCon(theDialog))->theTEHandle);
  841.     }
  842.     
  843. pascal void DrawScrollBar(DialogPtr theDialog, short theItem)
  844.     {        
  845. #pragma unused (theItem)
  846.  
  847.         Draw1Control(((pStyleTextInfo) GetWRefCon(theDialog))->theScrollBar);
  848.     }
  849.  
  850. /*
  851.     Name:    SetDrawProcForUserItem
  852.     Purpose: Installs a procedure that will be called when theItem needs
  853.              to be drawn.
  854. */
  855. pascal void SetDrawProcForUserItem(DialogPtr theDialog, short theItem, ProcPtr theProc)
  856.     {
  857.         short  theType;
  858.         Handle theHandle;
  859.         Rect   itemRect;
  860.         
  861.         GetDItem(theDialog, theItem, &theType, &theHandle, &itemRect);
  862.         SetDItem(theDialog, theItem, theType, (Handle)theProc, &itemRect);
  863.     }
  864.     
  865. /*
  866.     Name:    FlashButton
  867.     Purpose: Provide visual effect of button having been
  868.              selected.
  869. */
  870.  
  871. pascal void FlashButton(DialogPtr theDialog, short theItem)
  872.     {
  873.         short    theType;
  874.         Handle   theHandle;
  875.         Rect     itemRect;
  876.         
  877.         GetDItem(theDialog, theItem, &theType, &theHandle, &itemRect);
  878.         
  879.         HiliteControl((ControlHandle)theHandle, inButton);
  880.         HiliteControl((ControlHandle)theHandle, 0);
  881.     }
  882.     
  883. /* 
  884.     Name:    ScrollVActionProc
  885.     Purpose: Called as scrollbar is tracked in buttons or page up/down.
  886.              Keeps text in sync with scrollBar
  887. */
  888. pascal void ScrollVActionProc(ControlHandle control, short part)
  889.   {
  890.         short  amount;
  891.         short  initialValue;
  892.         
  893.     if (part)
  894.       {
  895.                 switch (part) {
  896.                   case inUpButton:
  897.                     case inDownButton : amount = 24;
  898.                                         break;
  899.                   case inPageUp:
  900.                     case inPageDown   : amount = (**control).contrlRect.bottom - 
  901.                                                  (**control).contrlRect.top;
  902.                                         break;
  903.                                                             
  904.                 }   /* case */
  905.                 
  906.                 if (part == inUpButton || part == inPageUp)
  907.           amount = -amount; /* reverse direction */
  908.             
  909.                 initialValue = GetCtlValue(control);
  910.  
  911.               SetCtlValue(control, initialValue+amount); /* Pinned within Min/Max automatically */
  912.                 
  913.                 amount  = GetCtlValue(control)-initialValue;                
  914.                 
  915.                 if (amount)
  916.           TEScroll(0, -amount, ((pStyleTextInfo)GetWRefCon((**control).contrlOwner))->theTEHandle);
  917.  
  918.             }     /* if */
  919.     }  /* ScrollVActionProc */
  920.     
  921. /*
  922.     Name:    TrackTEPosn
  923.     Purpose: Ensures that the scrollbar value matches the position
  924.              of the text edit record.
  925. */
  926. pascal void TrackTEPosn(ControlHandle theControl, TEHandle theHTE)
  927.     {
  928.         short shouldBe;
  929.         
  930.       shouldBe = (**theHTE).viewRect.top - 
  931.                                 (**theHTE).destRect.top;
  932.                                 
  933.         if (GetCtlValue(theControl)!=shouldBe)
  934.             SetCtlValue(theControl,shouldBe);
  935.     }
  936.  
  937. /*
  938.     Name:    SetScrollLimit
  939.     Purpose: Ensures that the maximum value of the scrollbar is sufficient
  940.              to allow showing of all text, and no more.
  941. */
  942. pascal void SetScrollLimit(ControlHandle newScroll, TEHandle theHTE)
  943.     {
  944.         Point     teLimit;
  945.         short     currentMax;
  946.         short     currentValue;
  947.         TextStyle theStyle;
  948.         short     lineHeight;
  949.         short     fontAscent;
  950.         
  951.         currentMax = GetCtlMax(newScroll);
  952.         
  953.         /*
  954.             Scroll max should be position of bottom of bottom line when unscrolled
  955.             This is equal to
  956.               The position of the bottom line relative to current position +
  957.                 The amount currently scrolled -
  958.                 The height of the visible part
  959.         */
  960.                 
  961.         teLimit    = TEGetPoint((**theHTE).teLength, theHTE); // Position of bottom relative to current posn
  962.         
  963.         TEGetStyle((**theHTE).teLength, &theStyle, &lineHeight, &fontAscent,theHTE);        
  964.         teLimit.v += lineHeight-fontAscent; // Add in for descent - TEGetPoint is posn of baseline not bottom of chars
  965.         
  966.         teLimit.v    += ((**theHTE).viewRect.top -(**theHTE).destRect.top); // Amount already scrolled
  967.         
  968.         teLimit.v -= ((**theHTE).viewRect.bottom - (**theHTE).viewRect.top); // Height of page
  969.         
  970.         if (teLimit.v<0) // Cannot be negative
  971.             teLimit.v = 0;
  972.             
  973.         if (currentMax>teLimit.v)
  974.             {
  975.                 currentValue = GetCtlValue(newScroll);
  976.                 if (currentValue>teLimit.v)
  977.                     {
  978.                         TEScroll(0, teLimit.v - currentValue, theHTE);
  979.                         SetCtlValue(newScroll, teLimit.v);
  980.                     }
  981.                 SetCtlMax(newScroll, teLimit.v);
  982.             }
  983.             
  984.         if (currentMax<teLimit.v)
  985.             SetCtlMax(newScroll, teLimit.v);
  986.     }
  987.  
  988. #define kCompile   3
  989. #define kTextItem  4
  990. #define kScrollBar 5
  991.  
  992. pascal Boolean MyFilterProc(DialogPtr theDialog, EventRecord *myEvent, short *itemHit)
  993.     {
  994.       short         myPart;
  995.         WindowPtr     whichWindow;
  996.         TEHandle      newTE;
  997.         Boolean       extend;
  998.         GrafPtr       oldPort;
  999.         Point         mousePt;
  1000.         char          myKey;
  1001.         Boolean       returnVal;
  1002.         long          menuResult;
  1003.         Rect          teItemRect;
  1004.         Rect          scrollItemRect;
  1005.         ControlHandle newScroll;
  1006.         ControlHandle theControl;
  1007.         short         part;
  1008.         short         value;
  1009.         short         cntlCode;
  1010.         
  1011.         GetPort(&oldPort);
  1012.         
  1013.         returnVal = false;
  1014.         
  1015.         newTE     = ((pStyleTextInfo)GetWRefCon(theDialog))->theTEHandle;
  1016.         newScroll = ((pStyleTextInfo)GetWRefCon(theDialog))->theScrollBar;
  1017.         
  1018.         TEIdle(newTE);
  1019.         
  1020.         /* Maintain the cursor */
  1021.         
  1022.         SetPort(theDialog);
  1023.         GetMouse(&mousePt);
  1024.         
  1025.         GetRectOfDialogItem(theDialog, kTextItem,  &teItemRect);
  1026.         GetRectOfDialogItem(theDialog, kScrollBar, &scrollItemRect);
  1027.         
  1028.         if (PtInRect(mousePt, &teItemRect))
  1029.             SetCursor(&editCursor);
  1030.         else
  1031.             SetCursor(&qd.arrow);
  1032.             
  1033.         switch (myEvent->what) {
  1034.             case mouseDown: myPart = FindWindow(myEvent->where, &whichWindow);
  1035.                                             if (whichWindow==theDialog)
  1036.                                                 switch (myPart) {
  1037.                                                     case inContent:
  1038.                                                     case inGrow:        SetPort(whichWindow);
  1039.                                                                                     mousePt = myEvent->where;
  1040.                                                                                     GlobalToLocal(&mousePt);
  1041.  
  1042.                                                                                     extend = ((myEvent->modifiers & shiftKey) != 0);
  1043.                                                                                     if (PtInRect(mousePt, &(*(newTE))->viewRect))
  1044.                                                                                         {
  1045.                                                                                             TEClick(mousePt, extend, newTE);
  1046.                                                                                             TrackTEPosn(newScroll, newTE);
  1047.                                                                                         }
  1048.  
  1049.                                                                                     if (PtInRect(mousePt, &scrollItemRect))
  1050.                                                                                          {
  1051.                                                                                                  cntlCode = FindControl(mousePt, theDialog, &theControl);
  1052.                                                                                                 if (theControl)
  1053.                                                                                                     if (cntlCode == inThumb)
  1054.                                                                                                         {
  1055.                                                                                                             value = GetCtlValue(theControl);
  1056.                                                                                                             part  = TrackControl(theControl,
  1057.                                                                                                                                                      mousePt,
  1058.                                                                                                                                                      nil);
  1059.                                                                                                             if (part)
  1060.                                                                                                                 {
  1061.                                                                                                                     value -= GetCtlValue(theControl);
  1062.                                                                                                                     if (value)
  1063.                                                                                                                         TEScroll(0, value, newTE);
  1064.                                                                                                                 } /* if */
  1065.                                                                                                         }
  1066.                                                                                                     else
  1067.                                                                                                       if (cntlCode!=0)
  1068.                                                                                                           part = TrackControl(theControl, mousePt, (ProcPtr)ScrollVActionProc);
  1069.                                                                                             }
  1070.                                                                                     break;
  1071.                                                         
  1072.                                                     case inDrag:      DragWindow(whichWindow,
  1073.                                                                                                          myEvent->where,
  1074.                                                                                                          &qd.screenBits.bounds);
  1075.                                                                                     returnVal = true; /* Stops modal dialog beeping */
  1076.                                                                                     break;
  1077.                                                     
  1078.                                                     case inMenuBar: /* Allows turn on/off of ballon help */
  1079.                                                                                     menuResult = MenuSelect(myEvent->where);
  1080.                                                                                     break;                                                                                        
  1081.                                                     }
  1082.                                             break;
  1083.             case keyDown:
  1084.             case autoKey: /* Need hooks here for command keys if menus enabled */
  1085.                                         myKey = myEvent->message & charCodeMask;
  1086.                                         if (myKey==3)
  1087.                                             {
  1088.                                                 *itemHit = kCompile;
  1089.                                                 FlashButton(theDialog, kCompile);
  1090.                                                 returnVal = true;
  1091.                                             }
  1092.                                         else
  1093.                                             {
  1094.                                                 TEKey(myKey, newTE);
  1095.                                                 SetScrollLimit(newScroll, newTE);
  1096.                                                 TrackTEPosn(newScroll, newTE);
  1097.                                             }
  1098.                                         break;
  1099.                                         
  1100.             case activateEvt: if (((myEvent->modifiers & activeFlag) != 0))
  1101.                                                     if ((WindowPtr)myEvent->message == theDialog)
  1102.                                                         TEActivate(newTE);
  1103.                                                     else
  1104.                                                         DoActivate((WindowPtr)myEvent->message, true); /* Should not get here! */
  1105.                                                 else
  1106.                                                     if ((WindowPtr)myEvent->message == theDialog)
  1107.                                                         TEDeactivate(newTE);
  1108.                                                     else
  1109.                                                         DoActivate((WindowPtr)myEvent->message, false);
  1110.                                                         
  1111.                                                 break;
  1112.                                                 
  1113.             case updateEvt  : if (Ours((WindowPtr)myEvent->message))
  1114.                                                     DoUpdate(DPtrFromWindowPtr((WindowPtr)myEvent->message));
  1115.                                                 break;
  1116.         }
  1117.         
  1118.         SetPort(oldPort);
  1119.         
  1120.         return(returnVal);
  1121.     }
  1122.  
  1123. pascal OSErr EditMenuScript(short theMenu, short theItem)
  1124.  {
  1125.         short         resID;
  1126.         OSAID         myScriptID;
  1127.         OSErr         myErr;
  1128.         OSErr         ignoreErr;
  1129.         AEDesc        scriptTextDesc;
  1130.         DialogPtr     scriptEditDlog;
  1131.         short         itemHit;
  1132.         TEHandle      newTE;
  1133.         GrafPtr       oldPort;
  1134.         Rect          itemRect;
  1135.         OSAID         myCompiledID;
  1136.         Handle        myScript;
  1137.         Boolean       wholeMenu;
  1138.         ControlHandle myScrollBar;
  1139.         StyleTextInfo theStyleTextInfo;
  1140.         
  1141.         GetPort(&oldPort);
  1142.         
  1143.         /*
  1144.             Look for a script associated with theItem first,
  1145.             and if not found look for one associated with 
  1146.             the whole menu
  1147.         */
  1148.         
  1149.         wholeMenu = false;
  1150.         
  1151.         resID = (theMenu<<5) + theItem;
  1152.         
  1153.         myScriptID = GetScriptIDForResID(resID);
  1154.         
  1155.         if (myScriptID==kOSANullScript)
  1156.           {
  1157.                 resID = (theMenu<<5);
  1158.                 myScriptID = GetScriptIDForResID(resID);
  1159.                 wholeMenu = true;
  1160.             }
  1161.                 
  1162.         scriptEditDlog = GetNewDialog(400, nil, (WindowPtr)-1);                     
  1163.         SetPort(scriptEditDlog);
  1164.         /*
  1165.             Create a styled text edit record for the userItem
  1166.             and install it
  1167.         */
  1168.         GetRectOfDialogItem(scriptEditDlog, kTextItem,  &itemRect);
  1169.         
  1170.         InsetRect(&itemRect, 5, 5);
  1171.         
  1172.         newTE = TEStylNew(&itemRect, &itemRect);
  1173.         
  1174.         TEAutoView(true, newTE);
  1175.         
  1176.         SetDrawProcForUserItem(scriptEditDlog, kTextItem,(ProcPtr)DrawStyledTextEditRec);
  1177.         
  1178.         /*
  1179.             Now create a scrollbar and install it
  1180.         */
  1181.         
  1182.         GetRectOfDialogItem(scriptEditDlog, kScrollBar, &itemRect);
  1183.         
  1184.         myScrollBar = NewControl(scriptEditDlog,
  1185.                                  &itemRect,
  1186.                                                          "",
  1187.                                                          true,
  1188.                                                          0,
  1189.                                                          0,
  1190.                                                          32000, // Will be fixed up later - by SetScrollLimit()
  1191.                                                          scrollBarProc,
  1192.                                                          0);
  1193.                                                          
  1194.         SetDrawProcForUserItem(scriptEditDlog, kScrollBar,(ProcPtr)DrawScrollBar);
  1195.         
  1196.         /*
  1197.             Use the dialog window refcon to allow access to the 
  1198.             TEHandle and scrollHandle avoiding the use
  1199.             of globals
  1200.         */
  1201.         
  1202.         theStyleTextInfo.theTEHandle  = newTE;
  1203.         theStyleTextInfo.theScrollBar = myScrollBar;
  1204.         
  1205.         SetWRefCon(scriptEditDlog, (long) &theStyleTextInfo);
  1206.  
  1207.         /*
  1208.             Put the source of the script into the 
  1209.             text edit record
  1210.         */
  1211.         
  1212.         myErr = OSAGetSource(gScriptingComponent,
  1213.                                                  myScriptID,
  1214.                                                  typeStyledText,
  1215.                                                  &scriptTextDesc);
  1216.       GetStyledTextFromDescIntoTEHandle(&scriptTextDesc, newTE);
  1217.         
  1218.         ignoreErr = AEDisposeDesc(&scriptTextDesc);
  1219.         
  1220.         SetScrollLimit(myScrollBar, newTE);
  1221.         TrackTEPosn(myScrollBar, newTE);
  1222.         
  1223.         do {
  1224.             ModalDialog((ModalFilterProcPtr)MyFilterProc, &itemHit);
  1225.             switch (itemHit){
  1226.                 case ok        :
  1227.                 case kCompile  :  SetCursor(&waitCursor);
  1228.                                                     HLock((Handle)(**newTE).hText);
  1229.                                   myErr = AECreateDesc(typeChar,
  1230.                                                                                             (Ptr)*((**newTE).hText),
  1231.                                                                                             (**newTE).teLength,
  1232.                                                                                             &scriptTextDesc);
  1233.                                                                                             
  1234.                                                   HUnlock((Handle)(**newTE).hText);
  1235.                                                     
  1236.                                                     myCompiledID = 0; // Added for Gustav 1.0a8
  1237.                                                     myErr = OSACompile(gScriptingComponent,
  1238.                                                                                          &scriptTextDesc,
  1239.                                                                                          0,
  1240.                                                                                          &myCompiledID);
  1241.                                                                                          
  1242.                                                     ignoreErr = AEDisposeDesc(&scriptTextDesc);
  1243.                                                     
  1244.                                                     scriptTextDesc.dataHandle = nil;
  1245.                                                     
  1246.                                                   if (myErr==noErr)
  1247.                                                       {
  1248.                                                             myErr = OSAGetSource(gScriptingComponent,
  1249.                                                                                                      myCompiledID,
  1250.                                                                                                      typeStyledText,
  1251.                                                                                                      &scriptTextDesc);
  1252.                                                                                                      
  1253.                                                             /* Zap current contents and
  1254.                                                                replace with returned source */
  1255.                                                                  
  1256.                                                             TESetSelect(0, 32000, newTE);
  1257.                                                             TEDelete(newTE);
  1258.                                                             SetCtlValue(myScrollBar, 0); // We deleted all the text so it won't be scrolled anymore
  1259.                                                             
  1260.                                                             GetStyledTextFromDescIntoTEHandle(&scriptTextDesc, newTE);
  1261.                                                             
  1262.                                                             DrawStyledTextEditRec(scriptEditDlog, kTextItem);
  1263.                                                                                                  
  1264.                                                             ignoreErr = AEDisposeDesc(&scriptTextDesc);
  1265.                                                         }
  1266.                                                     else
  1267.                                                         {
  1268.                                                             DisplayErrorInScript(newTE);
  1269.                                                             itemHit  = 0; // Stop dialog going away
  1270.                                                         }
  1271.                                                         
  1272.                                                     SetScrollLimit(myScrollBar, newTE);
  1273.                                                     TrackTEPosn(myScrollBar, newTE);
  1274.                                                 
  1275.                                                     SetCursor(&qd.arrow);
  1276.                                                         
  1277.                                                     if (itemHit==ok)
  1278.                                                         if (myErr==noErr)
  1279.                                                             {
  1280.                                                                 // Swap this script for the old one unless whole menu 
  1281.                                                               
  1282.                                                                 if (wholeMenu)
  1283.                                                                     myScriptID = kOSANullScript;
  1284.                                                                     
  1285.                                                                 myErr = OSACopyID(gScriptingComponent,
  1286.                                                                                                      myCompiledID,
  1287.                                                                                                      &myScriptID);
  1288.                                                                                                      
  1289.                                                                 myErr = OSAStore(gScriptingComponent,
  1290.                                                                                                  myScriptID,
  1291.                                                                                                  typeOSAGenericStorage,
  1292.                                                                                                  0,
  1293.                                                                                                  &scriptTextDesc);
  1294.                                                                                                  
  1295.                                                                 if (myErr==noErr)
  1296.                                                                     {
  1297.                                                                         /* should prompt for whole menu if mod 32 == 0 */
  1298.                                                                       
  1299.                                                                         resID = (theMenu<<5) + theItem;
  1300.                                                                         
  1301.                                                                         /* Remove it if it's already in the prefs file */
  1302.                                                                         
  1303.                                                                         myScript = Get1Resource(kCompiledScriptType, resID);
  1304.                                                                         
  1305.                                                                         if (myScript!=nil && ResError()==noErr)
  1306.                                                                             RmveResource(myScript);
  1307.                                                                         
  1308.                                                                         /* And create a new resource */
  1309.                                                                         
  1310.                                                                         myScript = scriptTextDesc.dataHandle;
  1311.                                                                         
  1312.                                                                         HLock((Handle)myScript);
  1313.                                                                         HandToHand(&myScript);                                 
  1314.                                                                         AddResource(myScript, kCompiledScriptType, resID, "\pMenu Script");
  1315.                                                                         UpdateResFile(CurResFile());
  1316.                                                                         HUnlock((Handle)myScript);
  1317.                                                                         
  1318.                                                                         if (wholeMenu)
  1319.                                                                           AddMenuScript(resID, myScriptID);
  1320.                                                                     }
  1321.                                                                 myErr = AEDisposeDesc(&scriptTextDesc);
  1322.                                                             }
  1323.                                                         else
  1324.                                                             itemHit = -1;
  1325.                                                             
  1326.                                                     ignoreErr = OSADispose(gScriptingComponent,
  1327.                                                                                                  myCompiledID);
  1328.                                                     
  1329.                 case cancel    : 
  1330.                 case kTextItem : 
  1331.                 case kScrollBar: break;
  1332.             }
  1333.     } while (itemHit!=ok && itemHit!=cancel);
  1334.                 
  1335.         DisposeDialog(scriptEditDlog);
  1336.         
  1337.         SetPort(oldPort);
  1338.         
  1339.         return(noErr);
  1340.  }